﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Policy;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace GameNode
{
    class NodeGameLogic
   {
        private readonly GameField gameField;
        private readonly Drawer drawer;
        private readonly Random rnd;
        private List<ConsoleNode> nodes;
        private List<ConsoleNode> winnerNodes;
        private ConsoleNode target;
        private int nodeCount;
        private bool isNewRound;
        public NodeGameLogic(GameField gameField, Drawer drawer, int nodeCount)
        {
            this.gameField = gameField;
            this.drawer = drawer;
            this.nodeCount = nodeCount;

            rnd = new Random();
            nodes = new List<ConsoleNode>();
            winnerNodes = new List<ConsoleNode>();
            target = GenerateRandomTarget((char) 1, ConsoleColor.White);

        }

        public void InitializeNodeList()
        {
            nodes.Add(new ValeraNode(0, 0, 'V', ConsoleColor.Red));
            RandomPlacement(nodes);
        }
        public void StartGame()
        {
            InitializeNodeList();
            GenerateRandomNodes();
            bool isGameOver = false;
            do
            {
                Console.Clear();
                RandomPlacement(target);
                isNewRound = false;
                do
                {
                    drawer.DrawGameField(gameField, '0');
                    for (int i = 0; i < nodes.Count; i++)
                    {
                        nodes[i].Move(CheckPosition);
                    }
                    for (int i = 0; i < nodes.Count; i++)
                    {
                        if (IsNodeOnTarget(nodes[i]))
                        {
                            winnerNodes.Add(nodes[i]);
                            drawer.DrawListAndMessage(winnerNodes, gameField, 5, "Winners");
                            nodes.RemoveAt(i);

                            if (nodes.Count == 1)
                            {
                                drawer.DrawListAndMessage(nodes, gameField, 15, "Loosers");
                                isNewRound = true;
                                RandomPlacement(winnerNodes);
                            }
                        }
                    }
                    drawer.DrawNodeList(nodes);
                    drawer.DrawNode(target);
                    Thread.Sleep(100);
                }
                while (!isNewRound);

                Console.ReadKey();
                
                if (winnerNodes.Count == 1)
                {
                    isGameOver = true;
                }
                else
                {
                    nodes = winnerNodes;
                    winnerNodes = new List<ConsoleNode>();
                }

            } while (!isGameOver);
        }
    
       private ConsoleNode GenerateRandomNode(int nodeCount)
       {

           int randomX = 0;
           int randomY = 0;
           do
           {
               randomX = rnd.Next(gameField.X, gameField.Width + gameField.X);
               randomY = rnd.Next(gameField.Y, gameField.Height + gameField.Y);

           } while (!IsPositionFree(randomX, randomY));

            return  new ConsoleNode(randomX, randomY, (char)(nodeCount + 41),
                                        (ConsoleColor)rnd.Next(1, 15));
       }

        private ConsoleNode GenerateRandomTarget(char symbol, ConsoleColor color)
        {

            int randomX = 0;
            int randomY = 0;
            do
            {
                randomX = rnd.Next(gameField.X, gameField.Width + gameField.X);
                randomY = rnd.Next(gameField.Y, gameField.Height + gameField.Y);

            } while (!IsPositionFree(randomX, randomY));

            return new ConsoleNode(randomX, randomY, symbol, color);
        }

        private void GenerateRandomNodes()

        {
            for (int i = 0; i < nodeCount; i++)
            {
                nodes.Add(GenerateRandomNode(i));
            }
        }

       private bool IsPositionFree(int x, int y)
       {
            List<ConsoleNode> nodeCollection;
            if (isNewRound) nodeCollection = winnerNodes;
            else nodeCollection = nodes;
            foreach (var nd in nodeCollection)
            {
                if (nd.IsOnPosition(x,y))
                    return false;
            }
           return true;
       }

       private bool IsNodeOnTarget(ConsoleNode node)
       {
           if (node.X == target.X && node.Y == target.Y)
               return true;
           return false;
       }

        private void RandomPlacement(List<ConsoleNode> nodes)
        {
            int x;
            int y;
            foreach (var node in nodes)
            {
                do
                {
                   x = rnd.Next(gameField.X, gameField.Width + gameField.X);
                   y = rnd.Next(gameField.Y, gameField.Height + gameField.Y);

                } while (!IsPositionFree(x, y)) ;
                node.X = x;
                node.Y = y;
            }
        }

        private void RandomPlacement(ConsoleNode node)
        {
            int x;
            int y;
            do
            {
                x = rnd.Next(gameField.X, gameField.Width + gameField.X);
                y = rnd.Next(gameField.Y, gameField.Height + gameField.Y);

            } while (!IsPositionFree(x, y));
            node.X = x;
            node.Y = y;
        }

        private Position CheckPosition(int x, int y)
        {
            if (!IsPositionFree(x, y))
                return Position.Node;
            if (!gameField.IsOnField(x, y))
                return Position.Border;
            return Position.Free;
        }
    }

    public enum Position
    {
        Node,
        Border,
        Free
    }
}
